import re
from django.http import HttpResponseRedirect
from django.contrib import admin
from utils import get_prev_item, get_next_item, get_max

class OrderingAdmin(admin.ModelAdmin):
    ordering = ('order',)
    list_display = ('adm_move_up', 'adm_move_down')

    def __call__(self, request, url):
        if url:
            match = re.match('^move_(?P<direction>up|down)/(?P<pk>[^/]+)', url)
            if match:
                return self.move(request, match.group('direction'), match.group('pk'))
        print 'self', self
        return super(OrderingAdmin, self).__call__(request, url)

    def save_model(self, request, obj, form, change):
        if obj.order == 0:
            obj.order = get_max(self.get_objects(request), 'order') + 1
        obj.save()

    def changelist_view(self, request, extra_context=None):
        if extra_context is None: extra_context = {}
        return super(OrderingAdmin, self).changelist_view(request, extra_context)

    def get_objects(self, request=None):
        from django.contrib.admin.views.main import ChangeList, ERROR_FLAG
        try:
            cl = ChangeList(request, self.model, self.list_display, self.list_display_links, self.list_filter,
                self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self)
        except:
            raise
            #pass  # handling by parent
        return cl.query_set

    def redirect_after_move(self, request):
        return HttpResponseRedirect('../../?%s' % request.GET.urlencode())

    def move(self, request, direction, pk):
        objects = self.get_objects(request).order_by('order')
        if objects.values('order').distinct().count() != objects.count():
            self._reorder(objects)

        current = objects.get(id=pk)
        try:
            if direction == 'up':
                prev = get_prev_item(objects, 'order',  current.order)
                current.order, prev.order = prev.order, current.order
                prev.save()
            elif direction == 'down':
                next = get_next_item(objects, 'order',  current.order)
                current.order, next.order = next.order, current.order
                next.save()
            else:
                raise ValueError, 'Incorrect direction `%s`' % direction
        except AttributeError:
            pass

        current.save()
        return self.redirect_after_move(request)

    def _reorder(self, objects):
        for i, item in enumerate(objects):
            order = i + 1
            if item.order != order:
                item.order = order
                item.save()
